package cmd

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"time"

	"github.com/spf13/cobra"
	"gopkg.in/yaml.v3"
)

var (
	connectorType string
)

// connectorCmd represents the connector command
var connectorCmd = &cobra.Command{
	Use:   "connector",
	Short: "Manage connectors",
	Long:  `Manage DataFlare connectors.`,
}

// connectorListCmd represents the connector list command
var connectorListCmd = &cobra.Command{
	Use:   "list",
	Short: "List available connectors",
	Long:  `List available DataFlare connectors.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		// Create HTTP client
		client := &httpClient{
			baseURL: apiURL,
			apiKey:  apiKey,
			timeout: 30 * time.Second,
		}

		// Get connectors
		var response struct {
			SourceConnectors []string `json:"sourceConnectors"`
			SinkConnectors   []string `json:"sinkConnectors"`
		}
		err := client.get(context.Background(), "/api/connectors", &response)
		if err != nil {
			return err
		}

		// Output
		switch outputFormat {
		case "json":
			json, err := json.MarshalIndent(response, "", "  ")
			if err != nil {
				return err
			}
			fmt.Println(string(json))
		case "yaml":
			yaml, err := yaml.Marshal(response)
			if err != nil {
				return err
			}
			fmt.Println(string(yaml))
		default:
			fmt.Println("SOURCE CONNECTORS")
			for _, connector := range response.SourceConnectors {
				fmt.Println(connector)
			}
			fmt.Println("\nSINK CONNECTORS")
			for _, connector := range response.SinkConnectors {
				fmt.Println(connector)
			}
		}

		return nil
	},
}

// connectorInfoCmd represents the connector info command
var connectorInfoCmd = &cobra.Command{
	Use:   "info",
	Short: "Get connector information",
	Long:  `Get information about a DataFlare connector.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		// Create HTTP client
		client := &httpClient{
			baseURL: apiURL,
			apiKey:  apiKey,
			timeout: 30 * time.Second,
		}

		// Get connector info
		var response struct {
			Type        string                 `json:"type"`
			Description string                 `json:"description"`
			Config      map[string]interface{} `json:"config"`
		}
		err := client.get(context.Background(), fmt.Sprintf("/api/connectors/%s", connectorType), &response)
		if err != nil {
			return err
		}

		// Output
		switch outputFormat {
		case "json":
			json, err := json.MarshalIndent(response, "", "  ")
			if err != nil {
				return err
			}
			fmt.Println(string(json))
		case "yaml":
			yaml, err := yaml.Marshal(response)
			if err != nil {
				return err
			}
			fmt.Println(string(yaml))
		default:
			fmt.Println("CONNECTOR")
			fmt.Printf("Type: %s\n", response.Type)
			fmt.Printf("Description: %s\n", response.Description)
			fmt.Println("\nCONFIG")
			for key, value := range response.Config {
				fmt.Printf("%s: %v\n", key, value)
			}
		}

		return nil
	},
}

// httpClient is a simple HTTP client for the DataFlare API
type httpClient struct {
	baseURL string
	apiKey  string
	timeout time.Duration
}

// get sends a GET request to the API
func (c *httpClient) get(ctx context.Context, path string, v interface{}) error {
	// Create HTTP client
	client := &http.Client{
		Timeout: c.timeout,
	}

	// Create request
	req, err := http.NewRequestWithContext(ctx, "GET", c.baseURL+path, nil)
	if err != nil {
		return err
	}

	// Set headers
	if c.apiKey != "" {
		req.Header.Set("Authorization", fmt.Sprintf("Bearer %s", c.apiKey))
	}

	// Send request
	resp, err := client.Do(req)
	if err != nil {
		return err
	}
	defer resp.Body.Close()

	// Check response
	if resp.StatusCode != http.StatusOK {
		var apiError struct {
			Code    string `json:"code"`
			Message string `json:"message"`
		}
		err = json.NewDecoder(resp.Body).Decode(&apiError)
		if err != nil {
			return fmt.Errorf("HTTP error: %d %s", resp.StatusCode, resp.Status)
		}
		return fmt.Errorf("%s: %s", apiError.Code, apiError.Message)
	}

	// Decode response
	err = json.NewDecoder(resp.Body).Decode(v)
	if err != nil {
		return err
	}

	return nil
}

func init() {
	rootCmd.AddCommand(connectorCmd)

	// Add subcommands
	connectorCmd.AddCommand(connectorListCmd)
	connectorCmd.AddCommand(connectorInfoCmd)

	// Info command flags
	connectorInfoCmd.Flags().StringVar(&connectorType, "type", "", "Connector type")
	connectorInfoCmd.MarkFlagRequired("type")
}
